package weatehrcrowd.servlets;

import java.io.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import weathercrowd.model.*;
import weathercrowd.utilities.*;

/**
 * Servlet implementation class SchemaExportServlet
 */
@WebServlet("/SchemaExportServlet")
public class SchemaExportServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public SchemaExportServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		try {
			doGetOrPost(request, response);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		try {
			doGetOrPost(request, response);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @throws ParseException 
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) or HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGetOrPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ParseException {

		// TODO enable the following session operations once needed 
		HttpSession session = request.getSession();
		//SessionHelper.destroySession(session);
		
		PersistenceHelper.DropAllTables();
		PersistenceHelper.CreateTables();
	
		// TODO load data if any 
		long temprIdStart = 1;
		long rainfIdStart = 1;
		long locationId = 1;
		
		List<HistoricalTemperature> tempsBathurst = loadHistoricalTemperatureFrom(
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_temperature_data\\acorn.sat.minT.063005.daily.txt", 
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_temperature_data\\acorn.sat.maxT.063005.daily.txt", 
				"Bathurst", "063005", locationId++, temprIdStart, -33.43f, 149.56f);
				// or 33.42S 149.58E?
		temprIdStart += tempsBathurst.size();
		Location location063005 = tempsBathurst.get(0).getLocation();
		
		List<HistoricalTemperature> tempsCanberra = loadHistoricalTemperatureFrom(
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_temperature_data\\acorn.sat.minT.070351.daily.txt", 
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_temperature_data\\acorn.sat.maxT.070351.daily.txt", 
				"Canberra", "070351", locationId++, temprIdStart, -35.31f, 149.2f);
		
		temprIdStart += tempsCanberra.size();
		
		List<HistoricalTemperature> tempsWaggaWagga = loadHistoricalTemperatureFrom(
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_temperature_data\\acorn.sat.minT.072150.daily.txt", 
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_temperature_data\\acorn.sat.maxT.072150.daily.txt", 
				"Wagga Wagga", "072150", locationId++, temprIdStart, -35.16f, 147.46f);
		
		temprIdStart += tempsWaggaWagga.size();
		
		List<HistoricalRainfall> rainsBathurst = loadHistoricalRainfallFrom(
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_rainfall_data\\IDCJAC0009_063005_1800_Data.csv", 
				location063005, rainfIdStart);
		
		rainfIdStart += rainsBathurst.size();
		
		List<HistoricalRainfall> rainsCanberra = loadHistoricalRainfallFrom(
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_rainfall_data\\IDCJAC0009_070246_1800_Data.csv", 
				"Canberra", "070246", locationId++, rainfIdStart, -35.31f, 149.13f);
		
		rainfIdStart += rainsCanberra.size();
		 
		List<HistoricalRainfall> rainsWaggaWagga = loadHistoricalRainfallFrom(
				"D:\\Documents\\quanben\\Projects\\govhack2012\\raw_rainfall_data\\IDCJAC0009_072040_1800_Data.csv", 
				"Wagga Wagga", "072040", locationId++, rainfIdStart, -35.23f, 147.33f);
		
		rainfIdStart += rainsWaggaWagga.size();
		
		EntityManager em = SessionHelper.getEntityManager(session);
		EntityTransaction t = em.getTransaction();
		PersistenceHelper.beginTransaction(t);
		
		em.persist(tempsCanberra.get(0).getLocation());
		for (HistoricalTemperature temp : tempsCanberra) {
			em.persist(temp);
		}
		
		em.persist(tempsBathurst.get(0).getLocation());
		for (HistoricalTemperature temp : tempsBathurst) {
			em.persist(temp);
		}
		
		em.persist(tempsWaggaWagga.get(0).getLocation());
		for (HistoricalTemperature temp : tempsWaggaWagga) {
			em.persist(temp);
		}
		
		em.persist(rainsCanberra.get(0).getLocation());
		for (HistoricalRainfall rain : rainsCanberra) {
			em.persist(rain);
		}
		
		em.persist(rainsBathurst.get(0).getLocation());
		for (HistoricalRainfall rain : rainsBathurst) {
			em.persist(rain);
		}
		
		em.persist(rainsWaggaWagga.get(0).getLocation());
		for (HistoricalRainfall rain : rainsWaggaWagga) {
			em.persist(rain);
		}
		
		
		t.commit();
		
		response.setContentType("text/html");
		PrintWriter pw = response.getWriter();
		pw.printf("Database has successfully been created, <br>\n");
		pw.printf("Click <a href=\"index.html\">here</a> to go back to the index page.\n");
	}

	protected List<HistoricalTemperature> loadHistoricalTemperatureFrom(String minFile, String maxFile,
			String locationName, String bomid, long locationId, long tempIdStart, float latitude, float longitude) 
			throws IOException, ParseException {
		
		BomLocation location = new BomLocation();
		location.setBomId(bomid);
		location.setName(locationName);
		location.setId(locationId);
		location.setLatitude(latitude);
		location.setLongitude(longitude);
		
		return loadHistoricalTemperatureFrom(minFile, maxFile, location, tempIdStart);
	}
	
	
	protected List<HistoricalTemperature> loadHistoricalTemperatureFrom(String minFile, String maxFile,
			Location location, long tempIdStart) 
			throws IOException, ParseException {
		List<HistoricalTemperature> result = new LinkedList<HistoricalTemperature>();
		FileReader frMin = new FileReader(minFile);
		FileReader frMax = new FileReader(maxFile);
		BufferedReader rdMin = new BufferedReader(frMin);
		BufferedReader rdMax = new BufferedReader(frMax);
		
		String lnMin = rdMin.readLine();
		String lnMax = rdMax.readLine();
		// TODO process the first line if we want
				
		while (true) {
			String rawDate, value;
			float min = 99999, max = 99999;
			// dates of min and max are supposed to match
			lnMin = rdMin.readLine();
			if (lnMin == null) break;
			lnMax = rdMax.readLine();
			
			//System.out.printf("%s\n", lnMin);
			//System.out.printf("%s\n", lnMax);
			
			String[] parts;
			parts = lnMin.split(" +", 0);
			rawDate = parts[0];
			//System.out.printf("rawdate = %s\n", rawDate);
			value = parts[1];
			//System.out.printf("value = %s\n", value);
			min = Float.parseFloat(value);

			parts = lnMax.split(" +", 0);
			value = parts[1];
			max = Float.parseFloat(value);
			
			HistoricalTemperature temperature = new HistoricalTemperature();
			temperature.setMin(min);
			temperature.setMax(max);
			SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
			Date date = formatter.parse(rawDate);
			
			temperature.setDate(date);
			temperature.setLocation(location);
			temperature.setId(tempIdStart);
			tempIdStart++;
			
			result.add(temperature);
		}

		return result;
	}
	
	protected List<HistoricalRainfall> loadHistoricalRainfallFrom(String rainfallFile,
			String locationName, String bomid, long locationId, long tempIdStart, float latitude, float longitude) 
					throws IOException, ParseException {
		
		BomLocation location = new BomLocation();
		location.setBomId(bomid);
		location.setName(locationName);
		location.setId(locationId);
		location.setLatitude(latitude);
		location.setLongitude(longitude);
		return loadHistoricalRainfallFrom(rainfallFile, location, tempIdStart);
	
	}
	
	protected List<HistoricalRainfall> loadHistoricalRainfallFrom(String rainfallFile, 
			Location location, long tempIdStart) 
					throws IOException, ParseException {
		List<HistoricalRainfall> result = new LinkedList<HistoricalRainfall>();
		
		FileReader frRainf = new FileReader(rainfallFile);
		BufferedReader rdRainf = new BufferedReader(frRainf);
		
		rdRainf.readLine();	// header line
		// TODO process the first line if we want
			
		while (true) {
			String lnRain = rdRainf.readLine();
			
			if (lnRain == null) break;
			
			//System.out.printf("%s\n", lnRain);
			
			String[] parts = lnRain.split(",");
			
			SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
			Date date = formatter.parse(parts[2]+parts[3]+parts[4]);
			float amount = parts.length < 6 || parts[5].isEmpty()? 99999: Float.parseFloat(parts[5]);
			
			HistoricalRainfall rain = new HistoricalRainfall();
			rain.setDate(date);
			rain.setLocation(location);
			rain.setId(tempIdStart);
			rain.setAmount(amount);
			tempIdStart++;
			
			result.add(rain);
		}
		
		return result;
	}

}
